/*
 * PlaylistManagerPanel.java
 *
 * Created on June 10, 2006, 1:16 PM
 */
package com.bff.slimserver.musicjukebox.ui;

import com.bff.slimserver.music.MusicObjects;
import com.bff.slimserver.music.exceptions.PlaylistException;
import com.bff.bjj.ui.component.ColorProperties;
import com.bff.slimserver.musicjukebox.lib.JukeboxProperties;
import com.bff.bjj.ui.component.BJJPanel;
import com.bff.slimserver.musicjukebox.ui.components.PlaylistCellRenderer;
import com.bff.bjj.ui.component.BJJButton;
import com.bff.slimserver.musicjukebox.ui.components.SavedPlaylistPopupMenu;
import com.bff.slimserver.musicjukebox.ui.components.SavedPlaylistSongList;
import com.bff.bjj.utils.Utils;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.bff.slimserver.SlimDatabase;
import org.bff.slimserver.SlimPlaylist;
import org.bff.slimserver.SlimSavedPlaylistManager;
import org.bff.slimserver.events.PlaylistChangeEvent;
import org.bff.slimserver.events.PlaylistChangeListener;
import org.bff.slimserver.events.SavedPlaylistChangeEvent;
import org.bff.slimserver.events.SavedPlaylistChangeListener;
import org.bff.slimserver.exception.SlimConnectionException;
import org.bff.slimserver.exception.SlimDatabaseException;
import org.bff.slimserver.exception.SlimException;
import org.bff.slimserver.musicobjects.SlimPlaylistItem;
import org.bff.slimserver.musicobjects.SlimSavedPlaylist;

/**
 *
 * @author  bfindeisen
 */
public class PlaylistManagerPanel
        extends BJJPanel
        implements SavedPlaylistChangeListener, PlaylistChangeListener {

    private SlimPlaylist playlist;
    private SlimSavedPlaylist savedPlaylist;
    private SlimDatabase database;
    private SlimSavedPlaylistManager playlistManager;
    private DefaultListModel playlistSongsModel;
    private DefaultComboBoxModel playlistModel;
    private boolean needsReload;

    /** Creates new form PlaylistManagerPanel */
    public PlaylistManagerPanel() {
        super();
        playlistSongsModel = new DefaultListModel();
        playlistModel = new DefaultComboBoxModel();
        try {
            playlist = JukeboxProperties.getInstance().getPlaylist();
            database = JukeboxProperties.getInstance().getDatabase();
            playlistManager = JukeboxProperties.getInstance().getPlaylistManager();
        } catch (PlaylistException ex) {
            ex.printStackTrace();
        } catch (SlimConnectionException ex) {
            Logger.getLogger(PlaylistManagerPanel.class.getName()).log(Level.SEVERE, null, ex);
        }

        JukeboxProperties.getInstance().getSlimMonitor().addSavedPlaylistChangeListener(this);
        JukeboxProperties.getInstance().getSlimMonitor().addPlaylistChangeListener(this);
        playlistManager.addSavedPlaylistChangeListener(this);

        initComponents();
        listAllPlaylists();

        this.savedPlaylist = getSelectedPlaylist();

        MouseListener songlistPopupListener = new SonglistPopupListener();
        listSongList.addMouseListener(songlistPopupListener);

        progressBarLoadingPlaylist.setVisible(false);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPanel4 = new BJJPanel();
        lblStatus1 = new javax.swing.JLabel();
        jPanel2 = new BJJPanel();
        jLabel1 = new javax.swing.JLabel();
        cbPlaylists = new javax.swing.JComboBox();
        btnAppend = new BJJButton();
        btnReplace = new BJJButton();
        btnDeletePlaylist = new BJJButton();
        lblStatus = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        listSongList = new SavedPlaylistSongList();
        jPanel1 = new BJJPanel();
        progressBarLoadingPlaylist = new javax.swing.JProgressBar();
        jPanel3 = new BJJPanel();
        jButton1 = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();

        setLayout(new java.awt.BorderLayout());

        jPanel4.setLayout(new java.awt.BorderLayout());

        lblStatus1.setForeground(new java.awt.Color(255, 0, 0));
        jPanel4.add(lblStatus1, java.awt.BorderLayout.CENTER);

        jLabel1.setText("Saved Playlists:");
        jPanel2.add(jLabel1);

        cbPlaylists.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        cbPlaylists.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbPlaylistsActionPerformed(evt);
            }
        });
        jPanel2.add(cbPlaylists);

        btnAppend.setText("Append to Playing");
        btnAppend.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAppendActionPerformed(evt);
            }
        });
        jPanel2.add(btnAppend);

        btnReplace.setText("Replace Playing");
        btnReplace.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnReplaceActionPerformed(evt);
            }
        });
        jPanel2.add(btnReplace);

        btnDeletePlaylist.setText("Delete");
        btnDeletePlaylist.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDeletePlaylistActionPerformed(evt);
            }
        });
        jPanel2.add(btnDeletePlaylist);

        lblStatus.setForeground(ColorProperties.INFO_MESSAGE_FORGROUND);
        jPanel2.add(lblStatus);

        jPanel4.add(jPanel2, java.awt.BorderLayout.NORTH);

        add(jPanel4, java.awt.BorderLayout.PAGE_START);

        listSongList.setCellRenderer(new PlaylistCellRenderer());
        jScrollPane1.setViewportView(listSongList);

        add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jPanel1.setLayout(new java.awt.BorderLayout());

        progressBarLoadingPlaylist.setIndeterminate(true);
        progressBarLoadingPlaylist.setRequestFocusEnabled(false);
        progressBarLoadingPlaylist.setString("Loading Playlists");
        progressBarLoadingPlaylist.setStringPainted(true);
        jPanel1.add(progressBarLoadingPlaylist, java.awt.BorderLayout.NORTH);

        jPanel3.setLayout(new java.awt.GridBagLayout());

        jButton1.setText("Remove");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        jPanel3.add(jButton1, gridBagConstraints);

        jLabel2.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        jLabel2.setText("Drag and drop to resequence");
        jPanel3.add(jLabel2, new java.awt.GridBagConstraints());

        jPanel1.add(jPanel3, java.awt.BorderLayout.PAGE_END);

        add(jPanel1, java.awt.BorderLayout.PAGE_END);
    }// </editor-fold>//GEN-END:initComponents

    private void btnReplaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnReplaceActionPerformed
        try {
            setCursor(Utils.getHourglassCursor());
            SlimSavedPlaylist pl = (SlimSavedPlaylist) cbPlaylists.getSelectedItem();
            if (pl != null) {
                try {
                    getPlaylist().replacePlaylist(pl);
                    lblStatus.setText("Playlist " + pl.getName() + " replaced current playlist.");
                } catch (Exception e) {
                    e.printStackTrace();
                    lblStatus.setText("Problem appending playlist!");
                }
            }
        } finally {
            setCursor(Utils.getNormalCursor());
        }
    }//GEN-LAST:event_btnReplaceActionPerformed

    private void btnAppendActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAppendActionPerformed
        try {
            setCursor(Utils.getHourglassCursor());
            SlimSavedPlaylist pl = (SlimSavedPlaylist) cbPlaylists.getSelectedItem();
            if (pl != null) {
                try {
                    getPlaylist().addPlaylist(pl);
                    lblStatus.setText("Playlist " + pl.getName() + " appended.");
                } catch (Exception e) {
                    e.printStackTrace();
                    lblStatus.setText("Problem appending playlist!");
                }
            }
        } finally {
            setCursor(Utils.getNormalCursor());
        }
    }//GEN-LAST:event_btnAppendActionPerformed

    private void btnDeletePlaylistActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeletePlaylistActionPerformed
        try {
            setCursor(Utils.getHourglassCursor());
            SlimSavedPlaylist playlist = (SlimSavedPlaylist) cbPlaylists.getSelectedItem();
            if (playlist != null) {
                int n = JOptionPane.showConfirmDialog(this,
                        "Are You Sure You Want To Delete Playlist " + playlist.getName() + "?",
                        "Delete Playlist?",
                        JOptionPane.YES_NO_OPTION);
                if (n == JOptionPane.YES_OPTION) {
                    try {
                        getPlaylistManager().deleteSavedPlaylist(playlist);
                    } catch (SlimConnectionException ex) {
                        Logger.getLogger(PlaylistManagerPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    playlistModel.removeElement(playlist);
                }
            }
        } finally {
            setCursor(Utils.getNormalCursor());
        }
    }//GEN-LAST:event_btnDeletePlaylistActionPerformed

private void cbPlaylistsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPlaylistsActionPerformed

    if (!needsReload) {
        listSongs(getSelectedPlaylist());
        setSavedPlaylist(getSelectedPlaylist());
    } else {
        needsReload = false;
        listAllPlaylists();
    }
}//GEN-LAST:event_cbPlaylistsActionPerformed

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
    SlimPlaylistItem item = getSongList().getSelectedItem();

    if (item != null) {
        try {
            getPlaylistManager().deletePlaylistSong(savedPlaylist, item);
        } catch (SlimException ex) {
            Logger.getLogger(PlaylistManagerPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}//GEN-LAST:event_jButton1ActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAppend;
    private javax.swing.JButton btnDeletePlaylist;
    private javax.swing.JButton btnReplace;
    private javax.swing.JComboBox cbPlaylists;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lblStatus;
    private javax.swing.JLabel lblStatus1;
    private javax.swing.JList listSongList;
    private javax.swing.JProgressBar progressBarLoadingPlaylist;
    // End of variables declaration//GEN-END:variables

    private SavedPlaylistSongList getSongList() {
        return (SavedPlaylistSongList) listSongList;
    }

    private synchronized void listAllPlaylists() {
        try {
            MusicObjects.refreshSavedPlaylists();
            SlimSavedPlaylist selectedPlaylist = getSelectedPlaylist();
            progressBarLoadingPlaylist.setVisible(true);
            listSongList.setEnabled(false);
            cbPlaylists.setEnabled(false);
            playlistModel.removeAllElements();
            List<SlimSavedPlaylist> playlistList = new ArrayList<SlimSavedPlaylist>(MusicObjects.getSavedPlaylists());
            playlistSongsModel.clear();
            for (SlimSavedPlaylist pl : playlistList) {
                playlistModel.addElement(pl);
            }
            cbPlaylists.setModel(playlistModel);

            if (selectedPlaylist != null
                    && playlistList.contains(selectedPlaylist)) {
                cbPlaylists.setSelectedItem(selectedPlaylist);
            } else {
                listSongs((SlimSavedPlaylist) cbPlaylists.getSelectedItem());
            }
        } finally {
            progressBarLoadingPlaylist.setVisible(false);
            listSongList.setEnabled(true);
            cbPlaylists.setEnabled(true);
        }


    }

    private SlimSavedPlaylist getSelectedPlaylist() {
        try {
            return (SlimSavedPlaylist) cbPlaylists.getSelectedItem();
        } catch (Exception e) {
            return null;
        }
    }

    private void releadSongs(SlimSavedPlaylist playlist) {
        try {
            playlist.setItems(getPlaylistManager().listSongsForSavedPlaylist(playlist));
        } catch (SlimDatabaseException ex) {
            Logger.getLogger(PlaylistManagerPanel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SlimConnectionException ex) {
            Logger.getLogger(PlaylistManagerPanel.class.getName()).log(Level.SEVERE, null, ex);
        }

        if (playlist.equals(getSelectedPlaylist())) {
            listSongs(playlist);
        }
    }

    private void listSongs(SlimSavedPlaylist playlist) {
        playlistSongsModel.removeAllElements();
        if (playlist != null) {
            List<SlimPlaylistItem> songList =
                    new ArrayList<SlimPlaylistItem>(playlist.getItems());

            for (SlimPlaylistItem song : songList) {
                playlistSongsModel.addElement(song);
            }
        }
        ((SavedPlaylistSongList) listSongList).setModel(playlist, playlistSongsModel);
    }

    public SlimPlaylist getPlaylist() {
        return playlist;
    }

    public void setPlaylist(SlimPlaylist playlist) {
        this.playlist = playlist;
    }

    public SlimDatabase getDatabase() {
        return database;
    }

    public void setDatabase(SlimDatabase database) {
        this.database = database;
    }

    @Override
    public void playlistChanged(SavedPlaylistChangeEvent event) {
        switch (event.getId()) {
            case (SavedPlaylistChangeEvent.PLAYLIST_ADDED):
            case (SavedPlaylistChangeEvent.PLAYLIST_DELETED):
                listAllPlaylists();
                break;

            case (SavedPlaylistChangeEvent.ITEM_ADDED):
            case (SavedPlaylistChangeEvent.ITEM_CHANGED):
            case (SavedPlaylistChangeEvent.ITEM_DELETED):
            case (SavedPlaylistChangeEvent.ITEM_MOVED):
                releadSongs(event.getNewPlaylist());
                break;
        }
    }

    /**
     * @return the playlistManager
     */
    public SlimSavedPlaylistManager getPlaylistManager() {
        return playlistManager;
    }

    /**
     * @param playlistManager the playlistManager to set
     */
    public void setPlaylistManager(SlimSavedPlaylistManager playlistManager) {
        this.playlistManager = playlistManager;
    }

    /**
     * @return the savedPlaylist
     */
    public SlimSavedPlaylist getSavedPlaylist() {
        return savedPlaylist;
    }

    /**
     * @param savedPlaylist the savedPlaylist to set
     */
    public void setSavedPlaylist(SlimSavedPlaylist savedPlaylist) {
        this.savedPlaylist = savedPlaylist;
    }

    @Override
    public void playlistChanged(PlaylistChangeEvent event) {
        switch (event.getId()) {
            case (PlaylistChangeEvent.PLAYLIST_SAVED):
                listAllPlaylists();
                break;
        }
    }

    private class SonglistPopupListener extends MouseAdapter {

        public void mousePressed(MouseEvent evt) {
            if (SwingUtilities.isRightMouseButton(evt)) {
                maybeShowPopup(evt);

            }
        }

        public void mouseReleased(MouseEvent evt) {
            maybeShowPopup(evt);
        }

        private void maybeShowPopup(MouseEvent evt) {
            int row = listSongList.locationToIndex(evt.getPoint());

            if (row > -1) {
                listSongList.setSelectedIndex(row);

                SlimPlaylistItem song = (SlimPlaylistItem) playlistSongsModel.getElementAt(row);

                SavedPlaylistPopupMenu popupMenu = new SavedPlaylistPopupMenu(getSavedPlaylist(), song);

                if (evt.isPopupTrigger()) {
                    popupMenu.show(evt.getComponent(),
                            evt.getX(), evt.getY());
                }
            }
        }
    }
}
